#ifndef _KH_CORE_EXCEPTIONS_H
#define _KH_CORE_EXCEPTIONS_H
// This is included into the Common.h, so doesn't have the Common include

// Define a basic exception type
#define KH_DEF_EXC_CORE(TYPE, SUPERTYPE) \
    class KH_CORE_DECLSPEC TYPE: public SUPERTYPE { \
    public: \
        TYPE(const char* message = "Unknown " #TYPE): SUPERTYPE(message) {} \
        TYPE(str message): SUPERTYPE(message) {} \
        TYPE(const boost::format& fmt): SUPERTYPE(fmt) {} \
        virtual const char* GetTypeName() const { return #TYPE; } \
    };

#define KH_DEF_EXC_PY(TYPE, SUPERTYPE) \
    class KH_CORE_DECLSPEC TYPE: public SUPERTYPE { \
    public: \
        TYPE(const char* message = "Unknown " #TYPE): SUPERTYPE(message) {} \
        TYPE(str message): SUPERTYPE(message) {} \
        TYPE(const boost::format& fmt): SUPERTYPE(fmt) {} \
        virtual const char* GetTypeName() const { return #TYPE; } \
        virtual PyObject* GetPyExcType() const { return PyExc_##TYPE; } \
    };

// Default exception translation register
#define KH_REG_EXC(TYPE) register_exception_translator<TYPE>(&Translate_##TYPE);

namespace kharlia { namespace core { namespace exc {

    //extern PyObject* KharliaNativeException;

    void _InitExceptions();

    class KH_CORE_DECLSPEC Exception: public std::exception {
        str mMessage;

    public:
        Exception(const char* message = "Unknown Exception"): mMessage(message) {}
        Exception(str message): mMessage(message) {}
        Exception(const boost::format& fmt): mMessage(fmt.str()) {}

        inline str GetMessage() const { return mMessage; }
        virtual const char* GetTypeName() const { return "Exception"; }
        virtual PyObject* GetPyExcType() const { return PyExc_RuntimeError; }

        virtual const char* what() const throw() { return extract<const char *>(mMessage); }
    };

    KH_DEF_EXC_CORE(NullPointerError, Exception)
    // Exceptions that can be mapped to Python exception classes

    KH_DEF_EXC_CORE(PythonException, Exception)

    KH_DEF_EXC_PY(AttributeError, PythonException)
    KH_DEF_EXC_PY(IOError, PythonException)
    KH_DEF_EXC_PY(LookupError, PythonException)
        KH_DEF_EXC_PY(IndexError, LookupError)
        KH_DEF_EXC_PY(KeyError, LookupError)
    KH_DEF_EXC_PY(NameError, PythonException)
    KH_DEF_EXC_PY(RuntimeError, PythonException)
        KH_DEF_EXC_PY(NotImplementedError, RuntimeError)
    KH_DEF_EXC_PY(TypeError, PythonException)
    KH_DEF_EXC_PY(ValueError, PythonException)

} // namespace exc

using namespace exc;

}} // namespace kharlia::core

#endif